#include "atom.h"
#include "atomsem.h"
#include <pthread.h>
#include <stdlib.h>
#include <semaphore.h>


extern uint8_t atomSemCreate(ATOM_SEM *sem, uint8_t initial_count)
{
    sem_t* sema = (sem_t*)malloc(sizeof(sem_t));

    sem->save_ptr = sema;

    if (sem_init(sema, 0, initial_count) == 0) {
        return ATOM_OK;
    }

    return ATOM_ERROR;
}

extern uint8_t atomSemDelete(ATOM_SEM *sem)
{
    uint8_t ret = ATOM_ERROR;

    sem_t* sema = sem->save_ptr;

    if (sem_destroy(sema) == 0) {
        ret = ATOM_OK;
    }

    free(sema);

    return (ret);
}

extern uint8_t atomSemGet(ATOM_SEM *sem, int32_t timeout)
{
    sem_t* sema = sem->save_ptr;

    if (timeout < 0)
    {
        return sem_wait(sema) == 0 ? ATOM_OK : ATOM_ERROR;
    }
    else
    {
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);

        long tick_ns = (1000000000 / SYSTEM_TICKS_PER_SEC);
        long sec = timeout / SYSTEM_TICKS_PER_SEC;
        long nsec = (timeout % SYSTEM_TICKS_PER_SEC) * tick_ns;

        ts.tv_sec += sec;
        ts.tv_nsec += nsec;

        return sem_timedwait(sema, &ts) == 0 ? ATOM_OK : ATOM_ERROR;;
    }
}

extern uint8_t atomSemPut(ATOM_SEM *sem)
{
    sem_t* sema = sem->save_ptr;
    return sem_post(sema) == 0 ? ATOM_OK : ATOM_ERROR;
}

extern uint8_t atomSemResetCount(ATOM_SEM *sem, uint8_t count)
{
    sem_t* sema = sem->save_ptr;

    while (count > 0)
    {
        sem_post(sema);
        count--;
    }
    return 1;
}